home *** CD-ROM | disk | FTP | other *** search
- #include "util.h"
- #include "mmdf.h"
- /* */
- /* CH_NIFTP: NIFTP MAIL DONOR CHANNEL */
- /* */
- /* This module does all the hard work for the donor channel */
- /* Chris Bennett University College London 24/2/81 */
- /* */
- /* Rewritten to incorporate new release MMDF stuff and */
- /* to generally streamline the code */
- /* Steve Kille July 1982 */
- /* SEK Feb 84 Rewrite to reformat sender */
- /*
- /* CH_NIFTP: NIFTP MAIL DONOR CHANNEL */
-
- #include <signal.h>
- #include "ch.h"
- #include "ap.h"
- #include "jnt.h" /* JNT Mail return value definition */
-
- extern struct ll_struct *logptr;
-
- extern char *pn_quedir;
- /* Location of JNTmail queues for NIFTP */
-
- extern int ap_outtype; /* Default output format */
-
- extern Chan *chanptr; /* Current channel */
-
-
- char *pn_chname; /* Name of channel we are called as */
- char *pn_sender; /* Sender of the message being processed*/
- char *pn_msgfile; /* name of file with message in */
- char pn_fname[ LINESIZE ]; /* Name of file for NIFTP output */
- int pn_fd; /* fd of NIFTP ouput file */
- char pn_curhost[ LINESIZE ]; /* Host being processed */
- short firstadr; /* Boolean - first address for host */
-
- char jnt_hedsep[] = "\n\n";
- /* Separatpr between header and text */
- /* for JNT mail */
- char jnt_adrsep[] = ",\n"; /* Separator between addresses */
- /* for JNT mail */
-
- LOCVAR int inheader; /* flags for text copy */
- LOCVAR int donesender;
-
- /* This lot need to be glbal to allow */
- /* the structure to be initialised */
- LOCVAR char TSname [LINESIZE];
- /* The TS address to be handed down */
- LOCVAR char senderbuf [LINESIZE];
- LOCVAR char *vararray[] = {
- "file", pn_fname,
- "host", pn_curhost,
- "adr", TSname,
- "sender", senderbuf,
- 0, 0
- };
-
-
- extern char *index ();
- extern char *blt ();
- extern char *ap_p2s();
-
- /*
- */
-
-
- pn_init () /* session initialization */
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_init ()");
- #endif
- return (RP_OK);
- }
-
- pn_end (state) /* end of session */
- int state;
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_end (%d)", state);
- #endif
- return (RP_OK); /* no-op */
- }
-
- pn_sbinit () /* ready for submission */
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_sbinit()");
- #endif
- return (RP_OK);
- }
-
- pn_sbend () /* end of submission */
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_sbend ()");
- #endif
-
- return (RP_OK); /* no-op */
- }
-
- /* DELIVER MESSAGE TO NIFTP DONOR */
-
-
-
-
- pn_winit (chname, sender, msgfile)/* initialize for one message */
- char chname[], /* what channel coming in from */
- sender[], /* return address for error msgs */
- msgfile[]; /* name of file with msg text */
- {
- extern char *strdup ();
- AP_ptr ap;
- AP_ptr local,
- domain,
- route;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_winit");
- #endif
-
- if (pn_chname != (char *) 0)
- free (pn_chname);
- pn_chname = strdup (chname);
- if (pn_sender != (char *) 0)
- free (pn_sender);
- ap = ap_s2tree (sender);
- if (ap != (AP_ptr) NOTOK)
- {
- ap_t2parts (ap, (AP_ptr *) 0, (AP_ptr *) 0, &local, &domain, &route);
- pn_sender = ap_p2s ((AP_ptr) 0, (AP_ptr) 0, local, domain, route);
- }
- /* ap_outtype will have corect value*/
-
- else
- ll_log (logptr, LLOGTMP, "Illegal sender '%s'", sender);
-
- if (pn_msgfile != (char *) 0)
- free (pn_msgfile);
- pn_msgfile = strdup (msgfile);
-
- ll_log (logptr, LLOGFTR, "c='%s', s='%s', f='%s'",
- pn_chname, (pn_sender==(char *)MAYBE)?"":pn_sender, pn_msgfile);
-
- if(pn_sender == (char *)MAYBE)
- return (RP_NS);
- return (RP_OK);
- }
-
-
- /*
- */
-
- pn_wainit () /* generate and open file */
- /* needed befor we can start */
- /* and get ready for next set of */
- /* addresses */
- {
- extern char *mktemp (); /* Stuff for filename genration */
- static char template[] = "niDDMM.aXXXXXX";
- char fi[6];
- struct tm *tm;
- long ti;
- short tries;
- extern char *multcpy ();
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_wainit ()" );
- #endif
-
- firstadr = TRUE; /* Ready for first host */
- ti = time(0);
- tm = gmtime(&ti);
- /* On a busy machine running a gateway, the PID's recycle quickly */
- /* so add the month and the day to the file to allow this to happen */
- if (template[2] == 'D') {
- /* not sure the %02 is portable - if not then you */
- /* will need to add some space detection code to */
- /* assignments below */
- (void) sprintf(fi, "%02d%02d", tm->tm_mon, tm->tm_mday);
- template[2] = fi[0];
- template[3] = fi[1];
- template[4] = fi[2];
- template[5] = fi[3];
- }
- /* File name generation extracted from submit.
- * make the unique part of the queue entry file name. if mktemp
- * can't do it, goose the value of the first char in the filename
- * part. mktemp uses qf_mfname, rather than qf_filnam, so that its
- * stat() can accurately tell if the name is unique. the goosing
- * strategy permits up to 1352 messages under the same process id.
- * mmdf will probably fall apart before that limit is hit.
- */
- for (tries = 51; tries-- >= 0; template[7]++)
- { /* template[7] limited to lower/upper */
- multcpy (pn_fname, pn_quedir, "/", template, (char *)0);
- /* add standard part of unique name */
- if (strcmp (mktemp(pn_fname), "/") != 0)
- break; /* add unique part */
- if (template[7] == 'z')
- template[7] = 'A' - 1; /* Case change - allow the ++ above */
- }
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "JNT mail file is = \"%s\"", pn_fname);
- #endif
-
- if (rp_isbad (pn_fd = creat (pn_fname, 0444)))
- {
- ll_err (logptr, LLOGBTR, "Failure to open file" );
- return (RP_FCRT);
- }
-
- return (RP_OK);
- }
- /*
- /* Process individual address */
- /* Produce JNT style address from host and address and place */
- /* into file. "," separator if not first one */
-
- extern AP_ptr ap_s2tree ();
-
- pn_wadr (host, adr)
- char *host; /* host official name */
- char *adr; /* rest of address / route */
- {
- char *jntadr; /* 733 /JNT format address */
- int len;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_wadr (h= '%s' a= '%s')", host, adr);
- #endif
-
- jntadr = adr;
- ll_log (logptr, LLOGFST, "JNT address = '%s'", jntadr);
-
- if (firstadr)
- {
- firstadr = FALSE;
- strcpy (pn_curhost, host);
- }
- else
- {
- len = strlen (jnt_adrsep);
- if (write (pn_fd, jnt_adrsep, len) != len)
- {
- ll_err (logptr, LLOGBTR, "File write error (separator)" );
- return (RP_FIO);
- }
- }
- len = strlen(jntadr);
- if (write (pn_fd, jntadr, len) != len)
- {
- ll_err (logptr, LLOGBTR, "File write error" );
- return (RP_FIO);
- }
-
- return (RP_AOK );
- }
-
- /*
- */
- LOCVAR char partialbuf [LINESIZE];
-
- pn_wtinit()
- /* End of addres list for this host */
- /* Write separtator between address */
- /* and start of body */
- {
- int len;
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_wtinit ()");
- #endif
-
- inheader = TRUE;
- donesender = FALSE;
- partialbuf [0] = '\0';
- ap_outtype = chanptr -> ch_apout;
- len = strlen (jnt_hedsep);
- if (write (pn_fd, jnt_hedsep, len) != len)
- {
- ll_err (logptr, LLOGBTR, "Failure writing separator" );
- return (RP_FIO);
- }
-
- return(RP_OK);
- }
- /*
- */
-
- #ifndef VIATRACE
-
- LOCVAR char *txt_sender = "Sender: ";
- LOCVAR char *txt_original = "Original-";
- /* Write block of text to file */
- pn_wtxt (buffer, len)
- char *buffer;
- int len;
- {
- int retval;
- char *front;
- char *back;
- char csav;
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_wttxt()");
- #endif
- /* whilst in header split into lines */
- /*for reformatting */
-
- if (inheader)
- {
- back = index (buffer, '\n');
- if (back == (char *) 0)
- {
- strcat (partialbuf, buffer);
- return (RP_OK);
- }
- back++;
- csav = *back;
- *back = '\0';
- strcat (partialbuf, buffer);
- if (rp_isbad (retval = pn_whdr (partialbuf, strlen (partialbuf))))
- return (retval);
- *back = csav;
-
-
- while ((front = index (back, '\n')) != (char *) 0)
- {
- front++;
- csav = *front;
- *front = '\0';
- if (rp_isbad (retval = pn_whdr (back, strlen (back))))
- return (retval);
- *front = csav;
- back = front;
- }
- if (!inheader) /* reached end of header */
- return (pn_wtxt (back, strlen (back)));
- strcpy (partialbuf, back);
- return (RP_OK);
- }
- else
- {
- if (write (pn_fd, buffer, len) != len)
- {
- ll_err (logptr, LLOGBTR, "Failure writing text to file" );
- return (RP_FIO);
- }
- }
- return(RP_OK);
- }
-
-
- /* */
-
- /* take single line and mungle it */
-
- LOCFUN pn_whdr (buffer, len)
- char *buffer;
- int len;
- {
- int namlen;
- char *cp;
- char name [LINESIZE];
- AP_ptr ap,
- local,
- domain,
- route;
-
- #ifdef DEBUG
- ll_log (logptr , LLOGFTR, "pn_whdr ('%s',%d)", buffer, len);
- #endif
-
- if (inheader)
- {
- if (buffer [0] == '\n')
- {
- inheader = FALSE;
- if (!donesender)
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "Outputting new sender '%s'",
- pn_sender);
- #endif
- namlen = strlen (txt_sender);
- if (write (pn_fd, txt_sender, namlen) != namlen)
- {
- ll_err (logptr, LLOGBTR, "Failure writing text to file" );
- return (RP_FIO);
- }
- namlen = strlen (pn_sender);
- if (write (pn_fd, pn_sender, namlen) != namlen)
- {
- ll_err (logptr, LLOGBTR, "Failure writing text to file" );
- return (RP_FIO);
- }
- if (write (pn_fd, "\n\n", 2) != 2)
- {
- ll_err (logptr, LLOGBTR, "Failure writing text to file" );
- return (RP_FIO);
- }
- }
- else
- if (write (pn_fd, "\n", 1) != 1)
- {
- ll_err (logptr, LLOGBTR, "Failure writing text to file" );
- return (RP_FIO);
- }
- return (RP_OK);
- }
-
- /* Now get name of line */
- /* just output continuations at once */
- if (!isspace (buffer [0]) &&
- (cp = index (buffer, ':')) != (char *) 0)
- {
- namlen = cp - buffer;
- blt (buffer, name, namlen);
- name [namlen]= '\0';
- if (lexequ (name, "via"))
- {
- namlen = strlen (txt_original);
- if (write (pn_fd, txt_original, namlen) != namlen)
- {
- ll_err (logptr, LLOGBTR, "Failure writing text to file" );
- return (RP_FIO);
- }
- }
-
- if (lexequ (name, "from"))
- {
- ap = ap_s2tree (cp + 1);
- if (ap != (AP_ptr) NOTOK)
- {
- ap_t2parts (ap, (AP_ptr *) 0, (AP_ptr *) 0,
- &local, &domain, &route);
- cp = ap_p2s ((AP_ptr) 0, (AP_ptr) 0,
- local, domain, route);
- if(cp == (char *)MAYBE)
- return (RP_NS);
- if (lexequ (pn_sender, cp))
- {
- donesender = TRUE;
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "Found matching From '%s'",
- cp);
- #endif
- }
- free (cp);
- }
- }
-
- if (lexequ (name, "sender"))
- {
- ap = ap_s2tree (cp + 1);
- if (ap != (AP_ptr) NOTOK)
- {
- ap_t2parts (ap, (AP_ptr *) 0, (AP_ptr *) 0,
- &local, &domain, &route);
- cp = ap_p2s ((AP_ptr) 0, (AP_ptr) 0,
- local, domain, route);
- if(cp == (char *)MAYBE)
- return (RP_NS);
- if (lexequ (pn_sender, cp))
- {
- donesender = TRUE;
-
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "Found matching Sender '%s'",
- cp);
- #endif
- }
- else
- {
- donesender = FALSE;
- /* in case a matchin From: field */
- namlen = strlen (txt_original);
- if (write (pn_fd, txt_original, namlen) != namlen)
- {
- ll_err (logptr, LLOGBTR,
- "Failure writing text to file" );
- return (RP_FIO);
- }
- }
- free (cp);
- }
- }
- }
- }
- if (write (pn_fd, buffer, len) != len)
- {
- ll_err (logptr, LLOGBTR, "Failure writing text to file" );
- return (RP_FIO);
- }
- return(RP_OK);
- }
-
- #else VIATRACE
-
- /*
- */
- /* Write block of text to file */
- /* simple non-munging version */
- pn_wtxt (buffer, len)
- char *buffer;
- int len;
- {
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_wttxt()");
- #endif
-
- if (write (pn_fd, buffer, len) != len)
- {
- ll_err (logptr, LLOGBTR, "Failure writing text to file" );
- return (RP_FIO);
- }
-
- return(RP_OK);
- }
- #endif VIATRACE
- /*
- /* End of text */
- /* Close file and pass to NIFTP */
- /* The host name is translated into the standard UCL TS address */
- /* of the form TSservice/hostaddres/service (e.g. tcp/isid/mail */
-
-
- pn_wtend (tmp_result)
- int tmp_result;
- {
- int i;
- char *p,*q;
- int pid; /* Process id for fork */
- int status; /* Status for wait */
- char buf [LINESIZE];
- int argc;
- char *argv[50];
- extern char *expand();
-
- #ifdef DEBUG
- ll_log (logptr, LLOGBTR, "pn_wtend ()");
- #endif
-
- if (close(pn_fd) == NOTOK) /* close file */
- {
- ll_err (logptr, LLOGBTR, "Failure to close file" );
- return (RP_LIO);
- }
-
- /* if status so far is bad unlink file */
- /* and pass on */
- if (rp_isbad (tmp_result))
- {
- if (unlink (pn_fname) == NOTOK) /* delete file */
- {
- ll_err (logptr, LLOGFAT, "Failure to unlink file '%s'", pn_fname);
- return (RP_FOPN);
- }
- ll_log (logptr, LLOGBTR, "Failure (%s) for file '%s'",
- rp_valstr (tmp_result), pn_fname);
- return (tmp_result);
- }
-
- /* Now extract the TS address */
- if (tb_k2val (chanptr->ch_table, TRUE,
- (chanptr->ch_host == NORELAY ? pn_curhost : chanptr->ch_host),
- TSname)!=OK)
- {
- ll_err (logptr, LLOGBTR, "TS address not found for '%s'",
- pn_curhost );
- return (RP_PARM);
- }
-
- /* 'quote' chars in sender */
- for (p=pn_sender, q=senderbuf; *p != '\0';)
- {
- switch (*p)
- {
- case '\"':
- case '\\':
- *q++ = '\\';
- *q++ = *p++;
- break;
- default:
- *q++ = *p++;
- break;
- }
- }
- *q = '\0';
- /* Now build execl string using */
- /* ch_ipcsstring as format */
- expand (buf, chanptr -> ch_confstr, vararray);
- ll_log (logptr, LLOGFST, "execl (%s)", buf);
-
- argc = cstr2arg (buf, 50, argv, ' ');
-
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "n=(%d) 0='%s', 1='%s', 2='%s', 3='%s', 4='%s'",
- argc, argv[0], argv[1], argv[2], argv[3], argv[4]);
- #endif
-
-
- if ((pid = fork()) == NOTOK)
- {
- ll_err (logptr, LLOGTMP, "Unable to fork for %s", argv[0]);
- if (unlink (pn_fname) == NOTOK) /* delete file */
- {
- ll_err (logptr, LLOGFAT, "Failure to unlink file '%s'", pn_fname);
- return (RP_FOPN);
- }
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "File: %s deleted", pn_fname);
- #endif
- return (RP_NET);
- }
- if (pid == 0) /* In child so do execl */
- {
-
- ll_log (logptr, LLOGFTR, "In the child");
- /* Close down all of the pipes to child */
-
- signal (SIGHUP, SIG_IGN);
- signal (SIGINT, SIG_IGN);
- signal (SIGQUIT, SIG_IGN);
-
- for (i = _NFILE - 1; i > 0; i--)
- close (i);
- open("/dev/null", 2);
- open("/dev/null", 1);
-
- execv (argv[0], &argv[1]);
-
- ll_log (logptr, LLOGTMP, "Unable to execl %s", argv[0]);
- exit (-1);
- }
-
- alarm (300); /* The NIFTP is not file size */
- /* dependent so 5 mins is ample */
- status = pgmwait (pid); /* Parent waits for child */
- alarm (0);
-
- if (status != JNT_OK)
- { /* Killed by alarm or general failure */
- if (unlink (pn_fname) == NOTOK) /* delete file */
- {
- ll_err (logptr, LLOGFAT, "Failure to unlink file '%s'", pn_fname);
- return (RP_FOPN);
- }
- #ifdef DEBUG
- ll_log (logptr, LLOGFTR, "File: %s deleted", pn_fname);
- #endif
- switch (status)
- {
- case JNT_TEMP:
- default: /* temporary error */
- ll_log (logptr, LLOGTMP,
- "Temporary failure (%d) for file: '%s' - requeued, h='%s'",
- status, pn_fname, pn_curhost);
- return (RP_DHST);
-
-
- case JNT_PERM: /* permanent error */
- ll_log (logptr, LLOGTMP,
- "Permanent USP failure (%d) - rejected", status);
- return (RP_NDEL);
- }
- }
-
-
- ll_log (logptr, LLOGFST, "Result is GOOD (%d)", status);
- /* For NIFTP evidence */
-
- return(RP_MOK);
- }
-